function bw = extractSilhouette(im, backgroundColor)
% Extracts the silhouette from the given color image.
% Returned as a binary image.
% Prerequisite: (almost) monochromatic background.
TOLERANCE = 5;

if ~exist('backgroundColor', 'var')
	nPixels = 100;
	[h, w, ~] = size(im);
	hw = h * w;
	indexes = randsample(hw, nPixels);
	sampledPixels = zeros(nPixels, 1, 'uint32');
	for i = 1:3  % R, G, B
		% packs all color channels together
		sampledPixels = bitor(bitshift(sampledPixels, 8), uint32(im(indexes)));
		indexes = indexes + hw;
	end

	colorPacked = mode(double(sampledPixels));
	br = bitshift(colorPacked, -16);
	bg = bitand(bitshift(colorPacked, -8), 255);
	bb = bitand(colorPacked, 255);
else
	br = backgroundColor(1);
	bg = backgroundColor(2);
	bb = backgroundColor(3);
end

im = double(im);

bw = ...
	(abs(im(:,:,1) - br) > TOLERANCE) & ...
	(abs(im(:,:,2) - bg) > TOLERANCE) & ...
	(abs(im(:,:,3) - bb) > TOLERANCE);

% removes small objects 
bw = bwareaopen(bw, 80, 8);
